package com.bytecub.udp.service.network.impl;

import com.bytecub.gateway.mq.excutor.DeviceMessageUpExecutor;
import com.bytecub.udp.domain.config.UdpProperties;
import com.bytecub.udp.service.network.IBcUdpServer;
import com.bytecub.udp.service.parser.DownMessageParser;
import com.bytecub.udp.service.parser.UdpAuthParser;
import com.bytecub.udp.service.parser.UdpProtocolParser;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *  * ByteCub.cn.
 *  * Copyright (c) 2020-2021 All Rights Reserved.
 *  * 
 *  * @author bytecub@163.com  songbin
 *  * @Date 2021/4/2  Exp $$
 *  
 */
@Slf4j
@Service
public class BcUdpServerImpl implements IBcUdpServer {
    @Autowired
    UdpProperties udpProperties;
    @Autowired
    private UdpAuthParser authParser;
    @Autowired
    private UdpProtocolParser protocolParser;
    @Autowired
    private DeviceMessageUpExecutor messageUpExecutor;
    @Autowired
    private DownMessageParser downMessageParser;

    private EventLoopGroup bossGroup = null;
    private Channel channel = null;
    @Override
    public void start() {
        try {
            if (!udpProperties.isEnable()) {
                log.info("UDP SERVER 禁用");
                return;
            }
            Bootstrap  b = new Bootstrap();
            bossGroup = udpProperties.isUseEpoll() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
            b.group(bossGroup)
                    .channel(udpProperties.isUseEpoll() ? EpollDatagramChannel.class : NioDatagramChannel.class)
                    // handler在初始化时就会执行
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .handler(udpProperties.isUseEpoll() ? new ChannelInitializer<EpollDatagramChannel>() {
                        @Override
                        protected void initChannel(EpollDatagramChannel epollDatagramChannel) throws Exception {
                                ChannelPipeline pipeline = epollDatagramChannel.pipeline();
                                pipeline.addLast(new BcUdpServerHandler(authParser, protocolParser, messageUpExecutor, downMessageParser));
                        }
                    }
                    :
                    new ChannelInitializer<NioDatagramChannel>() {
                        @Override
                        protected void initChannel(NioDatagramChannel nioDatagramChannel) throws Exception {
                            ChannelPipeline pipeline = nioDatagramChannel.pipeline();
                            pipeline.addLast(new BcUdpServerHandler(authParser, protocolParser, messageUpExecutor, downMessageParser));
                        }
                    }
                    )
                    .option(ChannelOption.SO_BROADCAST, true);
//                    .option(ChannelOption.SO_RCVBUF, 1024*1024*10) //读缓冲2M 这块最好使用操作系统自身的机制
//                    .option(ChannelOption.SO_SNDBUF, 1024*1024) //读缓冲1M 这块最好使用操作系统自身的机制

            channel = b.bind(udpProperties.getPort()).sync().channel();
            log.info("UDP SERVER 启动，监听端口:{}", udpProperties.getPort());
        } catch (Exception e) {
            log.error("启动udp server失败", e);
            System.exit(1);
        }

    }

    @Override
    public void stop() {
        try{
            if (udpProperties.isEnable()) {
                bossGroup.shutdownGracefully();
                bossGroup = null;
                channel.closeFuture().syncUninterruptibly();
                channel = null;
            }
        }catch (Exception e){
            log.warn("销毁UDP 异常", e);
        }

    }
}
